package com.acwing.partition4;

import java.io.*;

/**
 * @author `RKC`
 * @date 2022/4/24 22:17
 */
public class AC375蚂蚁 {

    private static final int N = 110;
    private static int[][] p1 = new int[N][2], p2 = new int[N][2];
    private static double[][] w = new double[N][N];
    private static double[] la = new double[N], lb = new double[N], upd = new double[N];
    private static boolean[] va = new boolean[N], vb = new boolean[N];
    //last[i]表示右部点i在交错树中的上一个右部点
    private static int[] match = new int[N], last = new int[N];
    private static int n;

    private static StreamTokenizer tokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    private static PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) throws IOException {
        n = nextInt();
        for (int i = 1; i <= n; i++) p2[i] = new int[]{ nextInt(), nextInt() };
        for (int i = 1; i <= n; i++) p1[i] = new int[]{ nextInt(), nextInt() };
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                //边权取相反数，转化为求二分图带权最大匹配
                w[i][j] = -Math.sqrt((p1[i][0] - p2[j][0]) * (p1[i][0] - p2[j][0]) + (p1[i][1] - p2[j][1]) * (p1[i][1] - p2[j][1]));
            }
        }
        km();
        for (int i = 1; i <= n; i++) writer.println(match[i]);
        writer.flush();
    }

    private static void km() {
        //初始化左部点顶标为其边权最小
        for (int i = 1; i <= n; i++) {
            la[i] = 1e-18;
            for (int j = 1; j <= n; j++) {
                la[i] = Math.max(la[i], w[i][j]);
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                va[j] = vb[j] = false;
                upd[j] = 1e18;
                last[j] = 0;
            }
            //从右部点st匹配的左部点match[st]开始dfs，一开始假设有一条0-l的匹配*
            int st = 0;
            match[0] = i;
            while (match[st] != 0) {
                if (dfs(match[st], st)) break;
                double delta = 1e18;
                for (int j = 1; j <= n; j++) {
                    if (!vb[j] && delta > upd[j]) {
                        delta = upd[j];
                        //下一次直接从最小的边开始dfs
                        st = j;
                    }
                }
                for (int j = 1; j <= n; j++) {
                    if (va[j]) la[j] -= delta;
                    if (vb[j]) lb[j] += delta;
                    else upd[j] -= delta;
                }
                vb[st] = true;
            }
            //倒推更新增广路
            while (st != 0) {
                match[st] = match[last[st]];
                st = last[st];
            }
        }
    }

    private static boolean dfs(int x, int fa) {
        va[x] = true;
        for (int y = 1; y <= n; y++) {
            if (vb[y]) continue;
            if (Math.abs(la[x] + lb[y] - w[x][y]) < 1e-6) {
                vb[y] = true;
                last[y] = fa;
                if (match[y] == 0 || dfs(match[y], y)) {
                    match[y] = x;
                    return true;
                }
            } else if (upd[y] > la[x] + lb[y] - w[x][y] + 1e-6) {
                upd[y] = la[x] + lb[y] - w[x][y];
                last[y] = fa;
            }
        }
        return false;
    }

    private static int nextInt() throws IOException {
        tokenizer.nextToken();
        return (int) tokenizer.nval;
    }
}
